package com.potenza.ws.endpoint;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.potenza.ws.utils.HTMLFilter;

import com.ruoyi.common.security.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint("/websocket/chat/{loginName}")
@Component
public class ChatWebSocketEndPoint {

    private  static RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    public  void setRedisTemplate(RedisTemplate<Object, Object> redisTemplate) {
        ChatWebSocketEndPoint.redisTemplate = redisTemplate;
    }

    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static final AtomicInteger onlineNum = new AtomicInteger(0);
    //concurrent包的线程安全Map，用来存放每个客户端对应的Session对象。
    private static final Set<Session> connections = new CopyOnWriteArraySet<>();

    public static final Map<String,Session> userConnections = new ConcurrentHashMap<>();
    private String loginName;
    private Session session;

    //处理四种事件
    //OnOpen  客户端发起连接 ，服务器端OnOpen响应
    //OnClose 客户端断开连接 ，服务器端OnCLose响应
    //OnMessage 客户端发送消息，服务器端OnMessage响应
    //OnError  客户端发生错误，服务器端OnError响应

    //关闭连接close()
    //发送消息send()

    // 处理连接建立
    @OnOpen
    public void onOpen(Session session,@PathParam("loginName")String loginName ) {
        // 获取登录名
        this.loginName = loginName;
        this.session = session;
        connections.add(session);
        userConnections.put(loginName,session);
        onlineNum.incrementAndGet();//i++
        String msg = String.format("欢迎 %s(%s)加入，当前在线人数 %d",loginName,session.toString(),onlineNum.get());
        System.out.println(msg);

        broadcast(loginName+ " 加入聊天室");
    }

    // 处理连接关闭
    @OnClose
    public void onClose(Session session,@PathParam("loginName")String loginName) {
        connections.remove(session);
        onlineNum.decrementAndGet();
        userConnections.remove(loginName);
        String msg = String.format("%s(%s) 退出，当前在线人数 %d",loginName,session.toString(),onlineNum.get());
        System.out.println(msg);

        broadcast(loginName+ " 退出聊天室");
    }

    /**
     * 接收到消息的监听方法
     * client write    ------>   server  read
     * server write    ------>   client  read
     * @param message  自定义协议
     *         {//群聊
     *             "to":'all',
     *             "content":'hello'
     *         }
     *         {//私聊
     *             "to":'zhangsan',
     *             "content":'hello'
     *         }
     */
    @OnMessage
    public void onMessage(Session session,String message,@PathParam("loginName")String loginName) {
        String msg = String.format("发送者%s(%s)发送消息： %s", loginName, session.toString(), message);
        System.out.println(msg);
        //解析消息类型
        Long userId = SecurityUtils.getUserId();
        JSONObject jsonObject = JSON.parseObject(message);
        String to = (String)jsonObject.get("to");
        String content = (String)jsonObject.get("content");

        if(to.equalsIgnoreCase("all")){
            broadcast(loginName+ ":" + HTMLFilter.filter(content));
        }else{
            Session sessionTo = userConnections.get(to);
            sessionTo.getAsyncRemote().sendText(loginName+ ":" + HTMLFilter.filter(content));
        }
        String[] split = content.split(",");
        Double location = Double.valueOf(split[0]);
        Double latitude = Double.valueOf(split[1]);
        redisTemplate.opsForGeo().add("SJJWD",new Point(location,latitude),loginName);


        System.out.println("CONTENT:"+content);
        System.out.println("LOGINNAME:"+loginName);
        System.out.println("USERID:"+userId);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        System.out.println("onError");
        throwable.printStackTrace();
    }
    /**
     * 关闭
     * @param session
     */
    public void close(Session session){
        try {
            session.close();
            connections.remove(session);
            onlineNum.decrementAndGet();
            System.out.println("关闭连接");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 发送消息到某一个Session
     * @param session
     * @param message
     */
    public void send(Session session,String message){
        session.getAsyncRemote().sendText(message);
    }

    /**
     * 广播消息
     * @param msg
     */
    private void broadcast(String msg) {
        for (Session session : connections) {
            synchronized (session) {
                session.getAsyncRemote().sendText(msg);//发送消息
            }
        }
    }

}
